package ru.fadeev.crammer;


import ru.fadeev.crammer.data.TestHistoryRecord;
import ru.fadeev.crammer.data.WordRecord;


/**
 * The TestManager class keeps information about test types and 
 * current test type. 
 * TestManager class also implements isNeededToTest function, 
 * that decides whether word should be tested or not based on word test history. 
 * @author Konstantin Fadeyev
 */
public class TestManager {
	// Constants
	public static final int TESTS_NUMBER = 4;
	// Test types
	public static final int TRANSLATION = 0;
	public static final int REVERSE_TRANSLATION = 1;
	public static final int GAPS_FILLING = 2;
	public static final int TRANSCRIPTION = 3;
	
	// User fields
	private int currentTestType;
	
	
	/**
	 * Creates instance of TestManager
	 */
	public TestManager() {	
		currentTestType = TRANSLATION;
	}

	
	/**
	 * Returns current test type. One of CRAMMING_RUS, CRAMMING_ENG,
	 * GAPS_FILLING or TRANSCRIPTION.
	 * @return current test type
	 */
	public int getCurrentTestType() {
		return currentTestType;
	}
	
	
	/**
	 * Sets new current test type. One of CRAMMING_RUS, CRAMMING_ENG,
	 * GAPS_FILLING or TRANSCRIPTION.
	 * @param currentTestType new current test type
	 */
	public void setCurrentTestType(int currentTestType)	{
		this.currentTestType = currentTestType;
	}

	/**
	 * Tests if word needs to be tested in test specified by 'currentTestType'
	 * @param wordRecord checked word
	 * @return true if word needs to be tested
	 */
	public boolean isNeededToTest(WordRecord wordRecord) {
		return isNeededToTest(wordRecord, currentTestType);
	}	
	
	/**
	 * Tests if word needs to be tested in test specified by parameter 'testType'
	 * @param wordRecord checked word
	 * @param testType test type
	 * @return true, if word needs to be tested
	 */
	public static boolean isNeededToTest(WordRecord wordRecord, int testType) {

		// If word is empty - there is nothing to test
		if(testType == TRANSCRIPTION && wordRecord.getTranscription()
				.trim().equals("")) {
			return false;
		}
		if(testType == TRANSLATION && wordRecord.getTranslation()
				.trim().equals("")) {
			return false;
		}

		// Algorithm to determine whether word needs to be tested or not:
		// Amount of time since last test after that word should be tested is calculated
		// by formula:  basePeriod * (factor)^(successNumber)
		// where basePeriod is time new word should be tested after, 
		// factor - after successful testing
		// time after word should be tested increase in factor times, 
		// successNumber - it's number of successful word testings
		// If word hasn't been successfully tested yet - function returns true.
		
		int successNumber = 0;
		long lastTestDate = wordRecord.getCreateDate();
		for(int i = 0; i < wordRecord.getHistorySize(); i++) {
			TestHistoryRecord historyRecord = 
				wordRecord.getHistoryRecord(i);
			if((historyRecord.getTestType() == testType)) {
				lastTestDate = historyRecord.getDate();
				if(historyRecord.isSuccessful()) {
					successNumber++;
				}
			}
		}
		long basePeriod;
		double factor; 

		switch(testType) {
		case TRANSLATION:
			basePeriod = Settings.getLong("translationBasePeriod");
			factor = Settings.getDouble("translationFactor");
			break;
		case REVERSE_TRANSLATION:
			basePeriod = Settings.getLong("reverseBasePeriod");
			factor = Settings.getDouble("reverseFactor");
			break;
		case TRANSCRIPTION:
			basePeriod = Settings.getLong("transcriptionBasePeriod");
			factor = Settings.getDouble("transcriptionFactor");
			break;
		default:
			basePeriod = Settings.getLong("gapsFillingBasePeriod");
			factor = Settings.getDouble("gapsFillingFactor");
		}
		
		long timeToTest = basePeriod * 
					Math.round( Math.pow(factor, successNumber) );
		
		if(lastTestDate + timeToTest < System.currentTimeMillis()) 
			return true;
		else
			return false;
	}
}

